/**
 * Copyright (c) 2008,中企动力华南研发中心 All rights reserved.
 */

package com.ce.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 逻辑、功能相关描述:复制VO中的属性，打印VO中的属性
 *
 * @author  luojunlin 编写日期：2008-1-23
 */

public final class BeanUtil {
	/**
	 * <p>Function: vo与do的互相转换，此方法是同步的</p>
	 * <ol>
	 * <li>可以对子Do进行转换,但有规则限制：1)Vo(Do)对像包括的为vo(Do)对象</li>
	 * <li>如果原对象属性的值为空或是集合框架(Set、List、Map),则不进行转换</li>
	 * <li>如果原对像有某属性，目标对象无该属性方法，则急略此值</li>
	 * <li>如果转换出错，将打印异常，但不抛出</li>
	 * </ol>
	 * @param sourceOBJ
	 * @param targetOBJ
	 * Create author:luojunlin
         * Create on:${date}
         * Edit author:
         * Edit on:
         * Why:
	 */
	@SuppressWarnings("unchecked")
	public static void convertVoAsDo(Object sourceOBJ, Object targetOBJ){
		try{
			//取得原对象和目标对象的列表
			BeanInfo sourceBi=Introspector.getBeanInfo(sourceOBJ.getClass());
			BeanInfo targetBi=Introspector.getBeanInfo(targetOBJ.getClass());
			PropertyDescriptor sourcePops[]=sourceBi.getPropertyDescriptors();
			PropertyDescriptor targetPops[]=targetBi.getPropertyDescriptors();
			Map sourceMap=new HashMap<String, Object>();

			//遍例原对像所有属性,并将值放入sourceMap,key为属性名
			for (PropertyDescriptor p : sourcePops){
				if (!p.getName().equals("class")) {
					if (java.util.Collection.class.isAssignableFrom(p.getPropertyType())) continue;
					Method readMethod = p.getReadMethod();
					if (readMethod == null) continue;
					Object result=readMethod.invoke(sourceOBJ, new Object[]{});

					sourceMap.put(p.getName(), result);
				}
			}

			//遍例目标对像所有属性,根据属性名调用set方法,结果从map中取,如果为null不进行操作
			for (PropertyDescriptor p : targetPops) {
				//目标对象的属性名
				String propertyName=p.getName();

				//vo转do,do转vo
				if (Pattern.matches("\\w*(V(O))", propertyName.toUpperCase())) {
					propertyName=propertyName.replaceAll("(\\w*)(V)(O|o)", "$1D$3");
				} else if (Pattern.matches("\\w*(D(O))", propertyName.toUpperCase())) {
					propertyName= propertyName.replaceAll("(\\w*)(D)(O|o)", "$1V$3");
				}

				//根据属性取原对像的值
				Object result=sourceMap.get(propertyName);

				if (result==null || "class".equals(p.getName())) continue;

				Method writeMethod = p.getWriteMethod();

				if (writeMethod == null) continue;
				// 开始转换
				//如果目标对像是一个vo或do 时，则对该子对象进行转换（递归调用）
				if (Pattern.matches("\\w*(VO|DO)", propertyName.toUpperCase())) {
					//构建属性对象
					Class cls=Class.forName(p.getPropertyType().getName());
					Object tempOBJ=cls.newInstance();
					//递归调用,以转换子对象
					convertVoAsDo(result, tempOBJ);
					try {
						writeMethod.invoke(targetOBJ,tempOBJ);
					} catch (IllegalArgumentException ae) {
//						StackTraceElement[] stes = ae.getStackTrace();
//						for (StackTraceElement element : stes) {
//							if (element.getClassName().equals(BeanUtil.class.getName())) {
//								System.err.print("class ["+element.getClassName()+"] ["+element.getLineNumber()+"]\n");
//								break;
//							}
//						}
//						System.err.println("exception message:["+ae.getMessage()+"] method name:["+writeMethod.getName()+"]");
					}
				} else {
					//若不是子对像，则直接转换
					try {
						writeMethod.invoke(targetOBJ,result);
					} catch (IllegalArgumentException ae) {
//						StackTraceElement[] stes = ae.getStackTrace();
//						for (StackTraceElement element : stes) {
//							if (element.getClassName().equals(BeanUtil.class.getName())) {
//								System.err.print("class: ["+element.getClassName()+"] line:["+element.getLineNumber()+"] ");
//								break;
//							}
//						}
//						System.err.println("message:["+ae.getMessage()+"]   method name:["+writeMethod.getName()+"]");
					}
				}

			}
		} catch (Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * Function: 打印targetObj所有属性值 注：本方法仅打印有公有的get方法的成员属性
	 *
	 * @param targetObj
	 * @param isCol
	 *            是否列向显示 Create author:luojunlin Create on:${date} Edit author:
	 *            Edit on: Why:
	 */
	public static void printfInfo(Object targetObj,boolean isCol)
	{
		try {
			Class targetClass=targetObj.getClass();
			BeanInfo bi=Introspector.getBeanInfo(targetClass);
			PropertyDescriptor pops[]= bi.getPropertyDescriptors();

			int count=0;//打印的字段计数器
			System.out.println("-------------"+targetClass.getName()+"-----------------");

			if (isCol) {//横向显示

				for (PropertyDescriptor item : pops) {

					if (!item.getName().equals("class")) {
						Object result=item.getReadMethod().invoke(targetObj, new Object[]{});
						System.out.println(item.getName()+"：\t"+result+"");
						count++;
					}

				}

			} else {//列向显示

				StringBuilder fieldName=new StringBuilder();
				StringBuilder fieldValue=new StringBuilder();

				for (PropertyDescriptor item : pops) {

					if (!item.getName().equals("class")) {
						Object result=item.getReadMethod().invoke(targetObj, new Object[]{});
						String tempName=formatString(item.getName(),20);
						fieldName.append(tempName+"\t");
						String tempValue=formatString("\t"+result+"\t",20);
						fieldValue.append(tempValue+"\t");
						count++;
					}

				}

				System.out.println(fieldName);
				System.out.println(fieldValue);

			}

			System.out.println("total property "+count+"");
			System.out.println("-------------------finshed------------------------");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Function: 格式化字符串，如果字符串不足len位，则在字符串前补足空格
	 * @param str
	 * @param len
	 * @return
	 * Create author:luojunlin
         * Create on:${date}
         * Edit author:
         * Edit on:
         * Why:
	 */
	static String formatString(String str,int len) {
		StringBuilder temp=new StringBuilder();

		if (str.length()<len) {

			for (int i=0; i<(len-str.length()); i++){
				temp.append(" ");
			}

		}

		temp.append(str);
		return temp.toString();
	}
}
